// miaux.h
// C++ classes, static-methods, etc, for performing some basic shader tricks
// with fewer lines of code in your mental ray shaders.
// A bunch of this was figured out from various places that discuss procedural shading
// My primary reference was at www.writingshaders.com
//

#ifndef LOFI_MIAUX_H
#define LOFI_MIAUX_H

#include <boost/operators.hpp>
#include <shader.h>

namespace lofi
{
	namespace miaux
	{
		class Color : 
			boost::addable<Color
		,	boost::subtractable<Color
		,	boost::multipliable<Color
		,	boost::dividable<Color
		,	boost::modable<Color
		> > > > >,
			boost::addable2<Color, miScalar
		,	boost::subtractable2<Color, miScalar
		,	boost::multipliable2<Color, miScalar
		,	boost::dividable2<Color, miScalar
		,	boost::modable2<Color, miScalar
		> > > > >
		{
		public:
			Color();
			Color(float value);
			Color(float r, float g, float b);
			Color(float r, float g, float b, float a);
			Color(miColor &color);
			Color(const Color &color);

			////////////////////////////////////////////////////////////////////
			// OPERATORS
			bool	operator==(const Color &rhs) const;

			Color&	operator=(const Color &rhs);
			Color&	operator+=(const Color &rhs);
			Color&	operator-=(const Color &rhs);
			Color&	operator*=(const Color &rhs);
			Color&	operator/=(const Color &rhs);
			Color&	operator%=(const Color &rhs);

			Color&	operator=(const float &rhs);
			Color&	operator+=(const float &rhs);
			Color&	operator-=(const float &rhs);
			Color&	operator*=(const float &rhs);
			Color&	operator/=(const float &rhs);
			Color&	operator%=(const float &rhs);
			// END OF OPERATORS
			////////////////////////////////////////////////////////////////////

			// Common functions
			void blend(const Color A, const Color B, float amount=0.5f);
			//Color clamp(Color min, Color max);
			//Color fit(Color min, Color max);

			// Accessors
			miScalar R();
			miScalar G();
			miScalar B();
			miScalar A();

			// Setters
			void R(miScalar r);
			void G(miScalar g);
			void B(miScalar b);
			void A(miScalar a);

			inline operator miColor()
			{
				return myColor;
			}

			// casting to scalar or float returns the luminance
			inline operator miScalar()
			{
				return _luminance<miScalar>();
			}

		private:
			miColor myColor;

			template <class T>
			inline T _luminance()
			{
				return (T)((0.2126*myColor.r)+(0.7152*myColor.g)+(0.0722*myColor.b));
			};
		};
	}
}

#endif // LOFI_MIAUX_H
